﻿using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net;
using System.Collections.Generic;
using DotRas;


namespace VPNLaunch
{
  public partial class vpnlaunch : Form
  {
    private UserSettings userSettings;
    private Boolean IsConnected { get; set; }
    private String Status { get; set; }
    private Boolean Reconnect { get; set; }
    private ConnectionInfo ActiveConnection { get; set; }

    public vpnlaunch()
    {
      InitializeComponent();
      this.userSettings = new UserSettings();
    }

    private void frm_ActiveConnectionChanged(object sender, VpnLaunchEventArgs e)
    {
      this.ActiveConnection = e.ActiveConnection;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      this.rasPhoneBook1.Open(true);
      this.IsConnected = (this.rasDialer1.GetActiveConnections().Count != 0);
      if (this.userSettings.Connections != null)
        this.ActiveConnection = this.userSettings.Connections.SingleOrDefault(c => c.DefaultConnection == true);
      this.statusItem.Enabled = this.IsConnected;
      notifyIcon1.Visible = true;
      this.Visible = false;
    }

    private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
    {
      contextMenuStrip1.Show(new Point(Cursor.Position.X - 65, Cursor.Position.Y));
    }

    private void ShowStatus(string msg)
    {
      this.Status = string.Format("{0}\n", this.Status += " *" + msg);
      notifyIcon1.ShowBalloonTip(5000, "VPNLaunch", this.Status, ToolTipIcon.Info);
    }

    private string GetIP()
    {
      foreach (IPAddress ip in Dns.GetHostEntry(System.Environment.MachineName).AddressList)
        if (ip.ToString().Contains("172.17."))
          return ip.ToString();
      return string.Empty;
    }

    private void runToolStripMenuItem_Click(object sender, EventArgs e)
    {
      try
      {
        LaunchVpn();
      }
      catch (ArgumentException ex)
      {
        ShowStatus(ex.Message);
      }
      catch (RasException ex)
      {
        ShowStatus(ex.Message);
      }
    }

    private void LaunchVpn()
    {
      this.Status = string.Empty;
      this.rasDialer1.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.User);
      if (this.ActiveConnection == null)
        throw new ArgumentException("No active connection selected.");
      RasEntry entry = this.rasPhoneBook1.Entries.SingleOrDefault(c => c.Id == this.ActiveConnection.Id);
      if (entry == null)
        throw new ArgumentException("Unable to locate entry");

      this.rasDialer1.EntryName = entry.Name;
      NetworkCredential credentials = new NetworkCredential();
      credentials.UserName = this.ActiveConnection.Username;
      credentials.Password = this.ActiveConnection.Password;
      credentials.Domain = this.ActiveConnection.Domain;
      ShowStatus(string.Format("Connecting To {0}", entry.PhoneNumber));
      try
      {
        this.rasDialer1.Dial(credentials);
      }
      catch (RasException)
      {
        throw;
      }
    }

    private void AddRoutes()
    {
      foreach (Route route in this.ActiveConnection.Routes)
      {
        route.Gateway = GetIP();
        ShowStatus(string.Format("Adding Route: {0}", route.ToString()));
        ProcessStartInfo pInfo = new ProcessStartInfo("route",
          String.Format(" add {0} mask {1} {2}",
            route.NetworkAddress,
            route.NetworkMask,
            route.Gateway));
        pInfo.UseShellExecute = false;
        pInfo.ErrorDialog = false;
        pInfo.CreateNoWindow = true;
        Process p = Process.Start(pInfo);
      }
    }

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void contextMenuStrip1_MouseLeave(object sender, EventArgs e)
    {
      contextMenuStrip1.Close();
    }

    private void ChangePropertiesToolStripMenuItem_Click(object sender, EventArgs e)
    {
      frmConnectionManager frm = new frmConnectionManager();
      frm.ActiveConnectionChanged += new frmConnectionManager.ActiveConnectionChangedHandler(frm_ActiveConnectionChanged);
      frm.Show();
    }

    private void rasConnectionWatcher1_Connected(object sender, RasConnectionEventArgs e)
    {
      this.IsConnected = true;
      ShowStatus("Connected!");
      AddRoutes();
    }

    private void rasConnectionWatcher1_Disconnected(object sender, RasConnectionEventArgs e)
    {
      this.Status = string.Empty;
      ShowStatus("Disconnected!");
      this.IsConnected = false;
      try
      {
        if (!this.Reconnect)
          LaunchVpn();
      }
      catch (ArgumentException ex)
      {
        ShowStatus(ex.Message);
      }
      catch (RankException ex)
      {
        ShowStatus(ex.Message);
      }
    }

    private void disconnectItem_Click(object sender, EventArgs e)
    {
      this.Reconnect = true;
      this.IsConnected = false;
      RasConnection entry = this.rasDialer1.GetActiveConnections().SingleOrDefault(c => c.EntryId == this.ActiveConnection.Id);
      if (entry != null)
      {
        entry.HangUp();
      }
      else
      {
        entry = this.rasDialer1.GetActiveConnections().FirstOrDefault();
        if (entry != null)
          entry.HangUp();
        else
          ShowStatus("Unable to find connection to disconnect.  Please disconnect Manually.");
      }
    }

    private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e)
    {
      this.runToolStripMenuItem.Enabled = !this.IsConnected;
      this.disconnectItem.Enabled = this.IsConnected;
    }

    private void statusItem_Click(object sender, EventArgs e)
    {
      status frm = new status();
      frm.Show();
    }

    private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
    {
      About frm = new About();
      frm.Show();
    }
  }
}